// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Code generated by sidekick. DO NOT EDIT.

use crate::Result;
#[allow(unused_imports)]
use gax::error::Error;

const DEFAULT_HOST: &str = "https://firestore.googleapis.com";

mod info {
    const NAME: &str = env!("CARGO_PKG_NAME");
    const VERSION: &str = env!("CARGO_PKG_VERSION");
    lazy_static::lazy_static! {
        pub(crate) static ref X_GOOG_API_CLIENT_HEADER: String = {
            let ac = gaxi::api_header::XGoogApiClient{
                name:          NAME,
                version:       VERSION,
                library_type:  gaxi::api_header::GAPIC,
            };
            ac.grpc_header_value()
        };
    }
}

/// Implements [Firestore](super::stub::Firestore) using a Tonic-generated client.
#[derive(Clone)]
pub struct Firestore {
    inner: gaxi::grpc::Client,
}

impl std::fmt::Debug for Firestore {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        f.debug_struct("Firestore")
            .field("inner", &self.inner)
            .finish()
    }
}

impl Firestore {
    pub async fn new(config: gaxi::options::ClientConfig) -> gax::client_builder::Result<Self> {
        let inner = gaxi::grpc::Client::new(config, DEFAULT_HOST).await?;
        Ok(Self { inner })
    }
}

impl super::stub::Firestore for Firestore {
    async fn get_document(
        &self,
        req: crate::model::GetDocumentRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::Document>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, true);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "GetDocument",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/GetDocument");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.name)
            .map(|s| s.as_str())
            .map(|v| format!("name={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::Document;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::Document>)
    }

    async fn list_documents(
        &self,
        req: crate::model::ListDocumentsRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::ListDocumentsResponse>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, true);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "ListDocuments",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/ListDocuments");
        let x_goog_request_params = [
            Some(&req)
                .map(|m| &m.parent)
                .map(|s| s.as_str())
                .map(|v| format!("parent={v}")),
            Some(&req)
                .map(|m| &m.collection_id)
                .map(|s| s.as_str())
                .map(|v| format!("collection_id={v}")),
        ]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::ListDocumentsResponse;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::ListDocumentsResponse>)
    }

    async fn update_document(
        &self,
        req: crate::model::UpdateDocumentRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::Document>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "UpdateDocument",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/UpdateDocument");
        let x_goog_request_params = [Some(&req)
            .and_then(|m| m.document.as_ref())
            .map(|m| &m.name)
            .map(|s| s.as_str())
            .map(|v| format!("document.name={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::Document;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::Document>)
    }

    async fn delete_document(
        &self,
        req: crate::model::DeleteDocumentRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<()>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, true);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "DeleteDocument",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/DeleteDocument");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.name)
            .map(|s| s.as_str())
            .map(|v| format!("name={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = ();
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, ()>)
    }

    async fn begin_transaction(
        &self,
        req: crate::model::BeginTransactionRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::BeginTransactionResponse>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "BeginTransaction",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/BeginTransaction");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.database)
            .map(|s| s.as_str())
            .map(|v| format!("database={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::BeginTransactionResponse;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::BeginTransactionResponse>)
    }

    async fn commit(
        &self,
        req: crate::model::CommitRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::CommitResponse>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "Commit",
            ));
            e
        };
        let path = http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/Commit");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.database)
            .map(|s| s.as_str())
            .map(|v| format!("database={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::CommitResponse;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::CommitResponse>)
    }

    async fn rollback(
        &self,
        req: crate::model::RollbackRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<()>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "Rollback",
            ));
            e
        };
        let path = http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/Rollback");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.database)
            .map(|s| s.as_str())
            .map(|v| format!("database={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = ();
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, ()>)
    }

    async fn partition_query(
        &self,
        req: crate::model::PartitionQueryRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::PartitionQueryResponse>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "PartitionQuery",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/PartitionQuery");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.parent)
            .map(|s| s.as_str())
            .map(|v| format!("parent={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::PartitionQueryResponse;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::PartitionQueryResponse>)
    }

    async fn list_collection_ids(
        &self,
        req: crate::model::ListCollectionIdsRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::ListCollectionIdsResponse>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "ListCollectionIds",
            ));
            e
        };
        let path = http::uri::PathAndQuery::from_static(
            "/google.firestore.v1.Firestore/ListCollectionIds",
        );
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.parent)
            .map(|s| s.as_str())
            .map(|v| format!("parent={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::ListCollectionIdsResponse;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::ListCollectionIdsResponse>)
    }

    async fn batch_write(
        &self,
        req: crate::model::BatchWriteRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::BatchWriteResponse>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "BatchWrite",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/BatchWrite");
        let x_goog_request_params = [Some(&req)
            .map(|m| &m.database)
            .map(|s| s.as_str())
            .map(|v| format!("database={v}"))]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::BatchWriteResponse;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::BatchWriteResponse>)
    }

    async fn create_document(
        &self,
        req: crate::model::CreateDocumentRequest,
        options: gax::options::RequestOptions,
    ) -> Result<gax::response::Response<crate::model::Document>> {
        use gaxi::prost::ToProto;
        let options = gax::options::internal::set_default_idempotency(options, false);
        let extensions = {
            let mut e = tonic::Extensions::new();
            e.insert(tonic::GrpcMethod::new(
                "google.firestore.v1.Firestore",
                "CreateDocument",
            ));
            e
        };
        let path =
            http::uri::PathAndQuery::from_static("/google.firestore.v1.Firestore/CreateDocument");
        let x_goog_request_params = [
            Some(&req)
                .map(|m| &m.parent)
                .map(|s| s.as_str())
                .map(|v| format!("parent={v}")),
            Some(&req)
                .map(|m| &m.collection_id)
                .map(|s| s.as_str())
                .map(|v| format!("collection_id={v}")),
        ]
        .into_iter()
        .flatten()
        .fold(String::new(), |b, p| b + "&" + &p);

        type TR = crate::google::firestore::v1::Document;
        self.inner
            .execute(
                extensions,
                path,
                req.to_proto().map_err(Error::deser)?,
                options,
                &info::X_GOOG_API_CLIENT_HEADER,
                &x_goog_request_params,
            )
            .await
            .and_then(gaxi::grpc::to_gax_response::<TR, crate::model::Document>)
    }
}
